package com.scs.application.modules.wm.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.scs.application.consts.SerialKeys;
import com.scs.application.core.exception.BusinessException;
import com.scs.application.core.mvc.controller.CrudController;
import com.scs.application.core.query.QueryContext;
import com.scs.application.core.query.QueryContextHolder;
import com.scs.application.core.threadLock.ThreadLock;
import com.scs.application.core.utils.DateUtils;
import com.scs.application.modules.base.enums.ExcelImportBaseDataConfig;
import com.scs.application.modules.sys.model.PageResult;
import com.scs.application.modules.sys.model.RestResult;
import com.scs.application.modules.wm.dto.PackDTO;
import com.scs.application.modules.wm.dto.RackingDTO;
import com.scs.application.modules.wm.dto.StockDTO;
import com.scs.application.modules.wm.entity.Stock;
import com.scs.application.modules.wm.mapper.StockMapper;
import com.scs.application.modules.wm.service.StockProcessLogService;
import com.scs.application.modules.wm.service.StockService;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 库存 前端控制器
 * </p>
 */
@RestController
@RequestMapping("/wm/stock")
public class StockController extends CrudController<StockService, Stock> {
    @Autowired
    private StockProcessLogService stockProcessLogService;
    @Autowired
    private StockService stockService;
    @Autowired
    @Lazy
    private StockMapper stockMapper;



    /**
     * 通过唯一码查询库存
     *
     * @param uniqueCode：唯一码
     * @return 库存实体
     */
    @GetMapping("/getStockByUniqueCode")
    public RestResult getStockByUniqueCode(@RequestParam("uniqueCode") String uniqueCode) {
        Stock stock = service.getStockByUniqueCode(uniqueCode);
        return RestResult.ok("获取数据成功", stock);
    }
    /**
     * 通过唯一码查询库存
     * 主要是RFID绑定多个SN
     * @param uniqueCode：唯一码
     * @return 库存实体
     * mxb
     */
    @GetMapping("/getStockListByUniqueCode")
    public RestResult getStockListByUniqueCode(@RequestParam("uniqueCode") String uniqueCode) {
        List<Stock> stock = service.getStockListByUniqueCode(uniqueCode);
        return RestResult.ok("获取数据成功", stock);
    }
    /**
     * 通过唯一码查询库存
     * 主要是RFID绑定多个SN
     * @param uniqueCode：唯一码
     * @return 库存实体
     * mxb
     */
    @GetMapping("/getStockListByRfid")
    public RestResult getStockListByRfid(@RequestParam("uniqueCode") String uniqueCode) {
        List<Stock> stockList = service.getStockListByUniqueCode(uniqueCode);
        Date date = new Date();
        stockList.stream().filter(stock -> DateUtils.compareDate(stock.getExpDate(), date)).findFirst().ifPresent(stock -> {
            throw new BusinessException("该SN【%s】效期【%s】已过期", stock.getSn(), DateUtils.format(stock.getExpDate()));
        });
        return RestResult.ok("获取数据成功", stockList);
    }

    @PostMapping("/pack")
    public RestResult pack(@RequestBody @Valid Stock stock) {
        if (stock.getLineId() != null) {
            if (stock.getLineId().equals("1")) {
                throw new BusinessException("未通过审核， 请审核通过后再进行加工!");
            }
            List<Stock> stockAllList = service.getStockByLineId(stock.getLineId());
            stock.setId(stockAllList.get(0).getId());
        }
        List<Stock> stockList = service.pack(stock.getId(), stock.getPackageUnit(),
                stock.getPackageQty().intValue(), SerialKeys.WM_STOCK_PROCESS_SN);

        //保存加工单历史!
        stockProcessLogService.saveProcessLog(stockList, stock.getId());

        return RestResult.ok("获取数据成功", service.getById(stock.getId()));
    }

    /**
     * 通过唯一码查询加工信息，移動端在用
     */
    @GetMapping("/getProcessInfoByUC")
    public RestResult getProcessInfoByUC(@RequestParam("uc") String uc, @RequestParam("ucType") String ucType, @RequestParam("warehouseId") String warehouseId) {
        return RestResult.ok("查询信息成功！", service.getProcessInfoByUC(uc, ucType, warehouseId));
    }

    /**
     * 通过入库单ID查询加工信息，移動端在用
     */
    @GetMapping("/getProcessInfoByWoId")
    public RestResult getProcessInfoByWoId(@RequestParam("workOrderId") String workOrderId) {
        return RestResult.ok("查询信息成功！", service.getProcessInfoByWoId(workOrderId));
    }

    @GetMapping("/getStockByUC")
    public RestResult getStockByUC(@RequestParam("uc") String uc, @RequestParam("ucType") String ucType, @RequestParam("warehouseId") String warehouseId) {
        return RestResult.ok("查询信息成功！", service.getStockByUC(uc, ucType, warehouseId));
    }

    @PostMapping("/mobilePack")
    public RestResult mobilePack(@RequestBody PackDTO packDTO) {
        List<Stock> stockList = service.pack(packDTO.getStockId(), packDTO.getToUnit(), packDTO.getQty(), packDTO.getSerialRule());
        stockProcessLogService.saveProcessLog(stockList, packDTO.getStockId());
        return RestResult.ok("加工成功！", stockList);
    }

    @PostMapping("/racking")
    public RestResult racking(@RequestBody RackingDTO rackingDTO) {
        service.racking(rackingDTO);
        return RestResult.ok("上架成功！");
    }

    @GetMapping("/unpack")
    public RestResult mobilePack(@RequestParam("stockId") String stockId) {
        service.unpack(stockId);
        return RestResult.ok("拆包成功！");
    }

    @GetMapping("/get_barcode")
    public RestResult getStockByLineId(@RequestParam("lineId") String lineId) {
        List<Stock> barorders = service.getStockByLineId(lineId);
        System.out.println(barorders.get(0));
        return RestResult.ok("success", barorders.get(0));
    }

    @PostMapping("/binding_rfid")
    public RestResult bindingRFID(@RequestBody Map map) {
        String sn = map.get("sn").toString();
        String rfid = map.get("rfid").toString();
        service.bindingRFID(sn, rfid);
        return RestResult.ok("绑定成功");
    }

    /**
     * 获取库存预警数据
     */
    @GetMapping("/get_stock_warning")
    public RestResult getStockWarning() {
        List<StockDTO> listStock = service.getStockWarning();
        return RestResult.ok("查询成", listStock);
    }

    /**
     * 获取库存账龄TOP50数据
     */
    @GetMapping("/get_stock_date")
    public RestResult getStockDate() {
        List<StockDTO> listStock = service.getStockDate();
        return RestResult.ok("查询成", listStock);
    }

    /**
     * 获取近效期库存TOP50数据
     */
    @GetMapping("/get_stock_exp_date")
    public RestResult getStockExpDate() {
        List<Stock> listStock = service.getStockExpDate();
        return RestResult.ok("查询成", listStock);
    }

    /**
     * 消耗获取耗材数据列表
     */
    @GetMapping("/pageForUse")
    public PageResult pageForUse() {
        QueryContext queryContext = QueryContextHolder.currentContext();

        IPage pageResult = service.pageForUse(queryContext);
        return PageResult.ok("查询成功", pageResult.getRecords(), pageResult.getTotal());
    }

    @GetMapping("/getStockByUCOnly")
    public RestResult getStockByUCOnly(@RequestParam("uc") String uc) {
        return RestResult.ok("查询成功！", service.getStockByUC(uc));
    }

    /**
     * @Description：RFID绑定和解绑
     * @Author wyt
     * @Date 2020/8/26
     */
    @GetMapping("/rfidBindOrUnbind")
    public RestResult rfidBindOrUnbind(String sn, String rfid, String opType) {
        if (StringUtils.isBlank(sn)) return RestResult.error("操作失败,缺少参数【sn】");
        if (StringUtils.isBlank(opType)) return RestResult.error("操作失败,缺少参数【opType】");
        if (!"bind,unbind".contains(opType)) return RestResult.error("操作失败,参数【opType】非法");
        String opTypeName = "解绑";
        sn = StringUtils.trim(sn);
        rfid = StringUtils.trim(rfid);
        if (opType.equals("bind")) {
            opTypeName = "绑定";
            if (StringUtils.isBlank(rfid)) return RestResult.error("操作失败,缺少参数【rfid】");
        } else {
            rfid = "";
        }
        List<String> snList = Arrays.asList(sn.split(","));
        if (snList.size() > 0) {
            for (String sn1 : snList) {
                service.rfidBindOrUnbind(sn1, rfid, opType);
            }
        }
        return RestResult.ok(opTypeName + "成功");
    }

    /**
     * 消耗红冲获取耗材数据列表
     */
    @GetMapping("/pageForRedType")
    public PageResult pageForRedType() {
        QueryContext queryContext = QueryContextHolder.currentContext();

        IPage pageResult = service.pageForRedType(queryContext);
        return PageResult.ok("查询成功", pageResult.getRecords(), pageResult.getTotal());
    }


    /**
     * 选择 获取数据列表 科室需求计划使用
     */
    @GetMapping("/pageForDemand")
    public PageResult pageForDemand(@RequestParam Map<String, Object> reqData) {
        QueryContext queryContext = QueryContextHolder.currentContext();
        Map<String, Object> userParam = null;
        //固定参数
        if (reqData.containsKey("userParam")) {
            JSONObject ob = JSON.parseObject(reqData.get("userParam") + "");
            userParam = Maps.newHashMap(ob);
        }

        IPage pageResult = service.pageForDemand(queryContext, userParam);
        return PageResult.ok("查询成功", pageResult.getRecords(), pageResult.getTotal());
    }

    /**
     * 查看盘点仓库的库存记录
     */
    @GetMapping("/pageForStockCheck")
    public PageResult pageForStockCheck(@RequestParam Map<String, Object> reqData) {
        Map<String, Object> userParam = null;

        if (reqData.containsKey("userParam")) {
            JSONObject ob = JSON.parseObject(reqData.get("userParam") + "");
            userParam = Maps.newHashMap(ob);
        }
        QueryContext queryContext = QueryContextHolder.currentContext();
        Page<?> pageResult = service.pageForStockCheck(queryContext, userParam);
        return PageResult.ok("查询成功", pageResult.getRecords(), pageResult.getTotal());
    }

    /**
     * 标签打印界面使用
     */
    @GetMapping("/pageForPrint")
    public PageResult pageForPrint() {
        QueryContext queryContext = QueryContextHolder.currentContext();
        IPage pageResult = service.pageForPrint(queryContext);
        return PageResult.ok("查询成功", pageResult.getRecords(), pageResult.getTotal());
    }


    /**
     * 更新标签打印数量即最近打印时间
     */
    @PostMapping(value = "/updatePrintNum")
    synchronized public RestResult updatePrintNum(@RequestBody Map<String, String> param) {
        service.updatePrintNum(JSON.parseArray(param.get("snArr")));
        return RestResult.ok();
    }


    /**
     * 上架
     */
    @GetMapping(value = "/upShelvesBatch")
    synchronized public RestResult upShelvesBatch(String warehouseId, String locationId) {
        return service.upShelvesBatch(warehouseId, locationId);
    }

    /**
     * 科室退货获取库存耗材数据列表
     */
    @GetMapping("/pageDeptReturn")
    public PageResult pageDeptReturn(@RequestParam Map<String, Object> reqData) {
        Map<String, Object> userParam = null;

        if (reqData.containsKey("userParam")) {
            JSONObject ob = JSON.parseObject(reqData.get("userParam") + "");
            userParam = Maps.newHashMap(ob);
        }
        QueryContext queryContext = QueryContextHolder.currentContext();

        IPage pageResult = service.pageDeptReturn(queryContext, userParam);
        return PageResult.ok("查询成功", pageResult.getRecords(), pageResult.getTotal());
    }

    /**
     * 耗材货位数据列表
     */
    @GetMapping("/getStockByMatr")
    public RestResult getStockByMatr(@RequestParam("matrId") String matrId) {
        List<Map<String,Object>> stockList = service.getStockByMatr(matrId);
        return RestResult.ok("获取数据成功", stockList);
    }

    /**
     * 获取数据列表 库存差异维护
     */
    @GetMapping("/pageForStockDiff")
    public PageResult pageForStockDiff() {
        QueryContext queryContext = QueryContextHolder.currentContext();
        IPage pageResult = service.pageForStockDiff(queryContext,null);
        return PageResult.ok("查询成功", pageResult.getRecords(), pageResult.getTotal());
    }

    /**
     * 库存差异处理
     */
    @GetMapping("/diffHandle")
    public RestResult diffHandle(String type,String stockId) {
        return RestResult.ok(service.diffHandle(type,stockId));
    }

    /**
     * 查询库存，同时也查询0库存表，一般用于科室退货、供应商退货、his退费、科室冲红等反向添加库存业务
     */
    @GetMapping("/pageStockWithZero")
    public PageResult pageStockWithZero(@RequestParam Map<String, Object> reqData) {
        Map<String, Object> userParam = null;

        if (reqData.containsKey("userParam")) {
            JSONObject ob = JSON.parseObject(reqData.get("userParam") + "");
            userParam = Maps.newHashMap(ob);
        }
        QueryContext queryContext = QueryContextHolder.currentContext();
        Page<?> pageResult = service.pageStockWithZero(queryContext, userParam);
        return PageResult.ok("查询成功", pageResult.getRecords(), pageResult.getTotal());
    }


    //将某一个仓库下的库存分组显示
    @PostMapping("/getListGroupByMatr")
    public RestResult getListGroupByMatr(@RequestBody Map<String, String> reqData) {
        String warehouseId = reqData.get("warehouseId");
        String matrIds = reqData.get("matrIds");
        QueryWrapper queryWrapper = Wrappers.<Stock>query();
        if (StringUtils.isNotBlank((warehouseId))) {
            queryWrapper.eq("warehouse_id",warehouseId);
        }
        if (StringUtils.isNotBlank(matrIds)) {
            List<String> matrIdList = Arrays.asList(matrIds.split(","));
            queryWrapper.in("matr_id",matrIdList);
        }

        return RestResult.ok("获取数据成功", service.getListGroupByMatr(queryWrapper));
    }

    /**
     * @Description：UDI绑定和解绑
     * @Author chen.wu
     * @Date 2021/7/15
     */
    @GetMapping("/udiBindOrUnbind")
    public RestResult udiBindOrUnbind(String snstr, String udi, String opType) {
        String str[] = snstr.split(",");
        List<String> snList= Arrays.asList(str);
        if (snList.size()==0) return RestResult.error("操作失败,缺少参数【sn】");
        if (StringUtils.isBlank(opType)) return RestResult.error("操作失败,缺少参数【opType】");
        if (!"bind,unbind".contains(opType)) return RestResult.error("操作失败,参数【opType】非法");
        String opTypeName = "解绑";
        udi = StringUtils.trim(udi);
        if (opType.equals("bind")) {
            opTypeName = "绑定";
            if (StringUtils.isBlank(udi)) return RestResult.error("操作失败,缺少参数【udi】");
            //查询UDI是否已绑定库存
            List<Stock> stockList=stockService.getStockListByUdi(udi);
            //已有绑定库存则对比库存属性
            if(stockList != null && stockList.size() > 0){
                //遍历sn
                for(String sn:snList){
                    sn = StringUtils.trim(sn);
                    //查询对应库存
                    Stock stock = service.getStockByUniqueCode(sn);
                    //新绑定的库存应与已绑定的耗材为同一耗材且效期批次相同
                    if(!stockList.get(0).getMatrId().equals(stock.getMatrId()) ){
                        return RestResult.error("该UDI已绑定的SN与该唯一码"+ sn +"不为同一耗材,请绑定其他UDI");
                    } else if(!stockList.get(0).getLot().equals(stock.getLot())){
                        return RestResult.error("该UDI已绑定的SN与该唯一码"+ sn +"批次不同,请绑定其他UDI", sn);
                    } else if(stockList.get(0).getExpDate().compareTo(stock.getExpDate()) != 0){
                        return RestResult.error("该UDI已绑定的SN与该唯一码"+ sn +"效期不同,请绑定其他UDI", sn);
                    }
                }
            }
        } else {
            udi = "";
        }
        for(String sn:snList){
            sn = StringUtils.trim(sn);
            service.udiBindOrUnbind(sn, udi, opType);
        }

        return RestResult.ok(opTypeName + "成功");
    }

    /**
     * 列表查询，选择使用
     */
    @GetMapping("/pageSelect")
    public PageResult pageSelect(@RequestParam Map<String, Object> reqData) {
        Map<String, Object> userParam = null;
        //固定参数
        if (reqData.containsKey("userParam")) {
            JSONObject ob = JSON.parseObject(reqData.get("userParam") + "");
            userParam = Maps.newHashMap(ob);
        }

        QueryContext context = QueryContextHolder.currentContext();
        IPage pageResult = stockMapper.pageSelect(context.getPage(), context.getWrapper(), userParam);
        return PageResult.ok("查询成功", pageResult.getRecords(), pageResult.getTotal());
    }


    /**
     * @description: 导入库存 下载导入模板
     **/
    @GetMapping("/excelDownloadTempForImportStock")
    public void excelDownloadTempForDataSplit(HttpServletResponse response, @RequestParam Map<String, String> reqData) {
        service.excelDownloadTemp(response,reqData, ExcelImportBaseDataConfig.getImportStock());
    }

    /**
     * @description: 导入库存 导入数据
     **/
    @RequestMapping(value = "/excelImportForImportStock", method = RequestMethod.POST)
    @ThreadLock(busType = "拆分商品")
    public RestResult excelImportForImportStock(@RequestParam(value = "file") MultipartFile file, @RequestParam Map<String, String> reqData) {
        try {
            return  RestResult.ok(service.excelImportForImportStock(file,reqData));
        }catch (Exception e) {
            return  RestResult.error(e.getMessage());
        }
    }

}
